 
#ifndef _GENERAL_
#define _GENERAL_


#include <windows.h>
#include <bitset>

///////////////////////////////////// 
//card macros 
#define RANK(c)	         ((c>>4)&0x0f) 
#define SUIT(c)          ((c>>0)&0x0f) 
#define ISCARDBACK(c)	 (c==0xff) 
#define ISUNKNOWN(c)	 (c==0) 
///////////////////////////////////// 

double gws(int chair, const char* name, bool& iserr){ 
	return (*m_pget_winholdem_symbol)(chair,name,iserr); 
} 

double gws(const char* name){ 
	bool iserr; 
	int mychair = (int)gws(0,"userchair",iserr); 
	return gws(mychair,name,iserr); 
}

bool hlset( int rank0, int rank1, int listnum, bool onoff ){
   return ((*m_phl1k)[listnum][rank0-2][rank1-2] = onoff);
}

bool hlget( int rank0, int rank1, int listnum ){
   return ((*m_phl1k)[listnum][rank0-2][rank1-2]);
}

//////////////////////////////////////////////////////////////////////////
//OWN FUNCS
//////////////////////////////////////////////////////////////////////////
int set_flush_rank(){

	bitset<16> srb( (int)gws("srankbits") ); 

	srb = (~srb ) >>= (int)gws("srankhiplayer"); 

	return (int)srb.count(); 
}
void set_card_values(){
	/*
		sets the card values
	*/

	//pocket cards
	card[0][0] = RANK(m_holdem_state[m_ndx].m_player[userchair].m_cards[0]);
	card[0][1] = SUIT(m_holdem_state[m_ndx].m_player[userchair].m_cards[0]);
	card[1][0] = RANK(m_holdem_state[m_ndx].m_player[userchair].m_cards[1]);
	card[1][1] = SUIT(m_holdem_state[m_ndx].m_player[userchair].m_cards[1]);

	//board cards
	for(int u=0;u<5;u++){
		card[u+2][0] = RANK(m_holdem_state[(m_ndx)&0xff].m_cards[u]);
		card[u+2][1] = SUIT(m_holdem_state[(m_ndx)&0xff].m_cards[u]);
	}

}
int set_rankhiplayer(){
	/*
		returns hi player rank
	*/
	if(card[0][0] > card[1][0]){
		return card[0][0];
	}
	else{
		return card[1][0];
	}
}
int set_rankloplayer(){
	/*
		returns lo player rank
	*/
	if(card[0][0] > card[1][0]){
		return card[1][0];
	}
	else{
		return card[0][0];
	}
}
bool set_suited(){
	/*
		1 - suited ; 0 -unsuited
	*/
	if(card[0][1] == card[1][1]){
		return 1;
	}
	else{
		return 0;
	}
}
int set_gap(){
	/*
		0 - pair ; 1 - connected ; 2 - one-gapper ...
	*/
	return rankhiplayer-rankloplayer;
}
bool set_SB(){
	/*
		checks if sblind was posted at the table
	*/
	for(int i=0;i<10;i++){
		if(m_holdem_state[(m_ndx)&0xff].m_player[i].m_currentbet < bblind-0.01){
			return 1;
		}
	}

	return 0;

}
/*
Returns the poker position bassed on some player dealposition (not Hero's only) value
-2 = BB
-1 = SB
0 = BTN
1 = CO
...
*/
int pos_pf(int dp)
{
   int res = 0;   
   int nopponentsdealt = (int)gws("nopponentsdealt");
   if (SB)
   {
      if (nopponentsdealt == 1) { int pos[2] = {{-2}, {-1}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 2) { int pos[3] = {{-1}, {-2}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 3) { int pos[4] = {{-1}, {-2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 4) { int pos[5] = {{-1}, {-2}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 5) { int pos[6] = {{-1}, {-2}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 6) { int pos[7] = {{-1}, {-2}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 7) { int pos[8] = {{-1}, {-2}, {5}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 8) { int pos[9] = {{-1}, {-2}, {6}, {5}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 9) { int pos[10] = {{-1}, {-2}, {7}, {6}, {5}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
   } else {
      if (nopponentsdealt == 1) { int pos[2] = {{0}, {-2}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 2) { int pos[3] = {{-2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 3) { int pos[4] = {{-2}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 4) { int pos[5] = {{-2}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 5) { int pos[6] = {{-2}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 6) { int pos[7] = {{-2}, {5}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 7) { int pos[8] = {{-2}, {6}, {5}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
      if (nopponentsdealt == 8) { int pos[9] = {{-2}, {7}, {6}, {5}, {4}, {3}, {2}, {1}, {0}}; res = pos[dp - 1]; }
   }
   return res;
}


int pf_pos(){
	/*
		returns the current position
	*/

	if(SB){
		if(nopponentsdealt == 1){
			int pos[2] = {{-2},{-1}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 2){
			int pos[3] = {{-1},{-2},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 3){
			int pos[4] = {{-1},{-2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 4){
			int pos[5] = {{-1},{-2},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 5){
			int pos[6] = {{-1},{-2},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 6){
			int pos[7] = {{-1},{-2},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 7){
			int pos[8] = {{-1},{-2},{5},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 8){
			int pos[9] = {{-1},{-2},{6},{5},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 9){
			int pos[10] = {{-1},{-2},{7},{6},{5},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
	}
	else{
		if(nopponentsdealt == 1){
			int pos[2] = {{0},{-2}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 2){
			int pos[3] = {{-2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 3){
			int pos[4] = {{-2},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 4){
			int pos[5] = {{-2},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 5){
			int pos[6] = {{-2},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 6){
			int pos[7] = {{-2},{5},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 7){
			int pos[8] = {{-2},{6},{5},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
		if(nopponentsdealt == 8){
			int pos[9] = {{-2},{7},{6},{5},{4},{3},{2},{1},{0}};
			return pos[dealposition-1];
		}
	}

	return 0;

}
bool is_seated(int chair){
	/*
		returns if player is seated at specified chair
	*/
	bitset<16> lok_play((int)gws("playersseatedbits"));

	return lok_play.test(chair);		
}
bool is_active(int chair){
	/*
		returns if player is active at specified chair
	*/
	bitset<16> lok_play((int)gws("playersactivebits"));

	return lok_play.test(chair);		
}
bool is_dealt(int chair){
	/*
		returns if player is dealt at specified chair
	*/
	bitset<16> lok_play((int)gws("playersdealtbits"));

	return lok_play.test(chair);		
}
bool is_playing(int chair){
	/*
		returns if player is playing at specified chair
	*/
	bitset<16> lok_play((int)gws("playersplayingbits"));

	return lok_play.test(chair);		
}



double set_ncurrentbet(){
	/*
		returns the maximum currentbet on the table
	*/
	double dumpvar = 0;

	for(int i = 0; i < 10;i++){
		if(is_playing(i) && m_holdem_state[(m_ndx)&0xff].m_player[i].m_currentbet > dumpvar){
			dumpvar = m_holdem_state[(m_ndx)&0xff].m_player[i].m_currentbet;
		}
	}

	return dumpvar;
}
int set_nopponentsbetting(){
	/*
		number of opponents betting
	*/
	int lok_count = 0;

	for(int k=0;k<10;k++){
		if(is_playing(k) && m_holdem_state[(m_ndx)&0xff].m_player[k].m_currentbet > 0 && k != userchair){
			lok_count++;
		}
	}

	return lok_count;

}
int set_nopponentscalling(){
	/*
		number of opponents betting
	*/
	int lok_count = 0;

	for(int k=0;k<10;k++){
		if(is_playing(k) && m_holdem_state[(m_ndx)&0xff].m_player[k].m_currentbet > ncurrentbet-0.01 
		&& k != userchair && m_holdem_state[(m_ndx)&0xff].m_player[k].m_currentbet < ncurrentbet+0.01){
			lok_count++;
		}
	}

	if(lok_count-1 > 0){
		return lok_count-1;
	}

	return 0;

}
int set_pf_entered(){
	/*
		returns amout of players who entered the pot
	*/
	if(SB){
		if(pf_my_pos == -2){
			return nopponentsbetting;
		}
		if(pf_my_pos== -1){
			return nopponentsbetting-1;
		}
		if(pf_my_pos> -1){
			return nopponentsbetting-2;
		}
	}
	else{
		if(pf_my_pos== -2){
			return nopponentsbetting;
		}
		if(pf_my_pos> -1){
			return nopponentsbetting-1;
		}
	}

	return 0;

}
double set_stack_depth(){
	/*
		returns the max(userbalance , raiserbalance)
	*/
	double dumpvar = 0;

	for(int i = 0; i < 10;i++){
		if(is_playing(i) && m_holdem_state[(m_ndx)&0xff].m_player[i].m_balance+m_holdem_state[(m_ndx)&0xff].m_player[i].m_currentbet-currentbet > dumpvar 
		&& i != userchair && m_holdem_state[(m_ndx)&0xff].m_player[i].m_currentbet > ncurrentbet-0.01
		&& m_holdem_state[(m_ndx)&0xff].m_player[i].m_currentbet < ncurrentbet+0.01){
			dumpvar = m_holdem_state[(m_ndx)&0xff].m_player[i].m_balance+m_holdem_state[(m_ndx)&0xff].m_player[i].m_currentbet-currentbet;
		}
	}
	if(balance > dumpvar){
		return balance;
	}

	return dumpvar;

}
void int_oh_symbols(){

	//GENERAL VARS
	SB = set_SB();
	ismyturn = (int)gws("ismyturn");
	betround = (int)gws("betround");
	userchair = (int)gws("userchair");
	bblind = gws("bblind");
	sblind = gws("sblind");
	ante=gws("ante");
	nchairs=(int)gws("nchairs");
	tournament=(bool)gws("istournament");
	limit=0;
	limit = (int)gws("lim")+1;
	dealposition = (int)gws("dealposition"); 
	dealerchair = (int)gws("dealerchair");
	nopponentsdealt = (int)gws("nopponentsdealt");


	// TODO
	handnumber=(int)gws("handsplayed");
	 
	tabletitle=m_holdem_state[(m_ndx)&0xff].m_title;

	//MONEY VARS
	totalpot = gws("pot");
	currentbet = m_holdem_state[(m_ndx)&0xff].m_player[userchair].m_currentbet;
	ncurrentbet = set_ncurrentbet();
	call = ncurrentbet-currentbet;
	balance = m_holdem_state[(m_ndx)&0xff].m_player[userchair].m_balance;
	stack_depth = set_stack_depth();

	//OPPONENT VARS
	nopponentsbetting = set_nopponentsbetting();
	nopponentscalling = set_nopponentscalling();

	//preflop
	pf_my_pos = pf_pos();
	pf_entered = set_pf_entered();

	//updating card values
	set_card_values();

	//updating hand values
	issuited = set_suited();
	rankhiplayer = set_rankloplayer();
	rankloplayer = set_rankhiplayer();
	gap = set_gap();

	//updating flush rank
	flushrank = set_flush_rank();

	// set bet sizes
	betstandardraise = (pf_entered+4)*bblind+0.01;
	betminraise = (2*nopponentscalling+(pf_entered-nopponentscalling)+6)*bblind+0.01;
	betxraise = (3+nopponentscalling)*(call+currentbet);
	betcall = 0.01;
    betfold=0;



}

#endif

